package com.yfqy.app.modules.fund.serviceimpl;

import com.yfqy.app.configure.Idgenerator.SnowflakeIdGenerator;
import com.yfqy.app.constant.GeneralConstants;
import com.yfqy.app.constant.SystemConfigConstants;
import com.yfqy.app.domain.entity.Customer;
import com.yfqy.app.domain.entity.CustomerFundAccount;
import com.yfqy.app.domain.entity.CustomerWithdrawal;
import com.yfqy.app.domain.mapper.CustomerFundAccountMapper;
import com.yfqy.app.domain.mapper.CustomerFundAccountRecordMapper;
import com.yfqy.app.domain.mapper.CustomerMapper;
import com.yfqy.app.domain.mapper.CustomerWithdrawalMapper;
import com.yfqy.app.enums.CustomerType;
import com.yfqy.app.enums.ErrorCode;
import com.yfqy.app.exception.BusinessException;
import com.yfqy.app.modules.fund.dto.UserAppliesWithdrawalDTO;
import com.yfqy.app.modules.fund.service.UserFundService;
import com.yfqy.app.modules.system.dto.WithdrawDTO;
import com.yfqy.app.modules.system.service.SystemConfigService;
import com.yfqy.app.security.login.LoginUserInfo;
import com.yfqy.app.util.AuthUserContext;
import com.yfqy.app.util.JSON;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;

@Service
@Slf4j
public class UserFundServiceImpl implements UserFundService {

    @Resource
    private CustomerMapper customerMapper;
    @Resource
    private CustomerFundAccountMapper customerFundAccountMapper;
    @Resource
    private CustomerFundAccountRecordMapper customerFundAccountRecordMapper;
    @Resource
    private CustomerWithdrawalMapper customerWithdrawalMapper;
    @Resource
    private SnowflakeIdGenerator idGenerator;
    @Resource
    private SystemConfigService systemConfigService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String userAppliesWithdrawal(UserAppliesWithdrawalDTO dto) {
        try {
            // 1. 验证用户身份和登录状态
            LoginUserInfo userInfo = validateUserLogin();
            Customer customer = validateDistributorUser(userInfo.getId());

            // 2. 验证提现金额
            CustomerFundAccount fundAccount = validateWithdrawalAmount(customer.getId(), dto.getAmount());

            // 3. 冻结资金
            freezeWithdrawalFunds(fundAccount.getId(), dto.getAmount());

            // 4. 创建提现申请记录
            createWithdrawalRecord(customer, dto);

            log.info("用户提现申请提交成功, userId: {}, amount: {}", customer.getId(), dto.getAmount());
            return ErrorCode.SUCCESS.name();

        } catch (BusinessException e) {
            log.warn("用户提现申请业务异常, userId: {}, amount: {}",
                    AuthUserContext.getLocalAuthUser() != null ? AuthUserContext.getLocalAuthUser().getId() : "unknown",
                    dto.getAmount(), e);
            throw e;
        } catch (Exception e) {
            log.error("用户提现申请系统异常, userId: {}, amount: {}",
                    AuthUserContext.getLocalAuthUser() != null ? AuthUserContext.getLocalAuthUser().getId() : "unknown",
                    dto.getAmount(), e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR.getCode(), "提现申请失败");
        }
    }

    /**
     * 验证用户登录状态
     */
    private LoginUserInfo validateUserLogin() {
        LoginUserInfo userInfo = AuthUserContext.getLocalAuthUser();
        if (userInfo == null || Objects.equals(userInfo.getId(), GeneralConstants.DEFAULT_USER_ID)) {
            throw new BusinessException(ErrorCode.USER_NOT_LOGIN);
        }
        return userInfo;
    }

    /**
     * 验证用户是否为分销商
     */
    private Customer validateDistributorUser(Long userId) {
        Customer customer = customerMapper.selectByPrimaryKey(userId);
        if (customer == null) {
            throw new BusinessException(ErrorCode.USER_NOT_EXIST);
        }
        if (customer.getIsLeader() != CustomerType.DISTRIBUTOR.getType()) {
            throw new BusinessException(ErrorCode.NOT_DISTRIBUTOR_USER);
        }
        return customer;
    }

    /**
     * 验证提现金额
     */
    private CustomerFundAccount validateWithdrawalAmount(Long customerId, BigDecimal amount) {
        // 验证金额有效性
        if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException(ErrorCode.APPLIES_WITHDRAWAL_AMOUNT_ERROR.getCode(), "提现金额必须大于0");
        }

        // 查询资金账户（加锁防止并发）
        CustomerFundAccount fundAccount = customerFundAccountMapper.selectByCustomerIdForUpdate(customerId);
        if (fundAccount == null) {
            throw new BusinessException(ErrorCode.FUND_ACCOUNT_NOT_EXIST);
        }

        // 验证余额是否足够
        if (amount.compareTo(fundAccount.getBalance()) > 0) {
            throw new BusinessException(ErrorCode.APPLIES_WITHDRAWAL_AMOUNT_ERROR.getCode(),
                    String.format("余额不足，当前余额：%.2f", fundAccount.getBalance()));
        }

        // 验证最小提现金额
        BigDecimal minWithdrawalAmount = getMinWithdrawalAmount();
        if (amount.compareTo(minWithdrawalAmount) < 0) {
            throw new BusinessException(ErrorCode.APPLIES_WITHDRAWAL_AMOUNT_ERROR.getCode(),
                    String.format("提现金额不能小于%.2f", minWithdrawalAmount));
        }

        return fundAccount;
    }

    /**
     * 冻结提现资金
     */
    private void freezeWithdrawalFunds(Long accountId, BigDecimal amount) {
        CustomerFundAccount updateFundAccount = new CustomerFundAccount();
        updateFundAccount.setId(accountId);
        updateFundAccount.setApplyingWithdrawal(amount); // 增加申请中金额

        int rows = customerFundAccountMapper.updateCustomerFundAccountByWithdrawal(updateFundAccount);
        if (rows == 0) {
            throw new BusinessException(ErrorCode.FUND_ACCOUNT_UPDATE_FAILED);
        }
    }

    /**
     * 创建提现申请记录
     */
    private void createWithdrawalRecord(Customer customer, UserAppliesWithdrawalDTO dto) {
        CustomerWithdrawal customerWithdrawal = new CustomerWithdrawal();
        customerWithdrawal.setId(idGenerator.nextId());
        customerWithdrawal.setCustomerId(customer.getId());
        customerWithdrawal.setWithdrawalNo(generateWithdrawalNo());
        customerWithdrawal.setAmount(dto.getAmount());
        customerWithdrawal.setWithdrawalType((byte) 1);
        customerWithdrawal.setAccountInfo(buildAccountInfo(customer));
        int rows = customerWithdrawalMapper.insert(customerWithdrawal);
        if (rows == 0) {
            throw new BusinessException(ErrorCode.WITHDRAWAL_APPLY_FAILED);
        }
    }

    /**
     * 生成提现单号（更规范的格式）
     */
    private String generateWithdrawalNo() {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String random = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999));
        return "WD" + timestamp + random;
    }

    /**
     * 构建账户信息JSON
     */
    private String buildAccountInfo(Customer customer) {
        return "{\"openid\":\"" + customer.getOpenid() + "\",\"nickname\":\"" + customer.getNickname() + "\"}";
    }

    /**
     * 获取最小提现金额（从配置或常量）
     */
    private BigDecimal getMinWithdrawalAmount() {
        String configValue = systemConfigService.getConfigValue(
                SystemConfigConstants.CONFIG_GROUP_DISTRIBUTION,
                SystemConfigConstants.CONFIG_KEY_WITHDRAW_SETTING);
        try {
            WithdrawDTO withdrawDTO = JSON.parse(configValue, WithdrawDTO.class);
            return withdrawDTO.getMin_amount();
        } catch (Exception e) {
            // 可以从系统配置获取，或者使用常量
            return new BigDecimal("1.00"); // 默认最小1元
        }
    }

}
